﻿using System;
using System.Dynamic;
using System.Linq.Expressions;

namespace DLR05
{
    /// <summary>
    /// This is the minimum required to invoke a dynamic method.
    /// </summary>
    /// <remarks>
    /// This is by no means as safe as it should be.  It needs to be cleaned up.
    /// </remarks>
    public class SimpleInvokeBinder : InvokeBinder
    {
        public SimpleInvokeBinder(CallInfo callInfo)
            : base(callInfo)
        {
        }

        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            if (target.LimitType.IsSubclassOf(typeof(Delegate)))
            {
                var parms = target.LimitType.GetMethod("Invoke").GetParameters();
                var callArgs = ExpressionEx.ConvertArguments(args, parms);
                return new DynamicMetaObject(
                    ExpressionEx.EnsureObjectResult(
                        Expression.Invoke(Expression.Convert(target.Expression, target.LimitType), callArgs)),
                    BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType));
            }

            return new DynamicMetaObject(
                Expression.Throw(
                    Expression.New(
                        typeof(Exception).GetConstructor(new[] { typeof(string) }),
                        Expression.Constant("Unable to call the function."))),
                BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType));
        }
    }
}